# -*- coding: utf-8 -*-
"""
Created on Fri Jul  3 19:20:16 2020
 
@author: 李秉华
"""

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import tree,datasets
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
import datetime

import xlwt

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # 空间三维画图

#规范化数据集，去除文件中的\n
def deleten():
    path1="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/dataSet.txt"
    path2="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/dataSet_deleten2.txt"
    f = open(path1)
    contents = f.read()
    f.close()
    new_contents = contents.replace('\n', '')
    f = open(path2, 'w')
    f.write(new_contents)
    f.close()
    return

#决策树与随机森林的模型训练
def TreeforestTest(dataSet, targetSet):
    X=dataSet
    y=targetSet
    
    #训练集路径
    pathgetTG="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/dataSet_deleten2.txt"
    
    ds=[]
    ts=[]
    
    for line in open(pathgetTG, encoding='utf-8'):
        if line[:2]=="[[":
            ds=eval(line)
        else:
            ts=eval(line)
    
    for i in range(len(ts)):
        ts[i]*=100
    
    #数据清洗
    ds=ds[70:]
    ts=ts[70:]
    
    tmp=0
    while tmp<len(ds):
        if(ds[tmp][0]>=1):
            ds.pop(tmp)
            ts.pop(tmp)
            tmp-=1
        tmp+=1

    #分割训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1/6, random_state=4)
    
    
    #决策树
    estimators={}
    estimators['tree'] = tree.DecisionTreeClassifier(criterion='gini',random_state=8)
    
    # 随机森林
    # n_estimators: 树的数量
    # bootstrap: 是否随机有放回
    # n_jobs: 可并行运行的数量
    estimators['forest'] = RandomForestClassifier(n_estimators=14,criterion='gini',
              bootstrap=True,n_jobs=6,random_state=9,max_features=2) 
    
    for k in estimators.keys():
        start_time = datetime.datetime.now()
        print('----%s----' % k)             #打印当前模型为决策树或随机森林
        estimators[k] = estimators[k].fit(X_train, y_train)
        pred = estimators[k].predict(X_test)
        print(pred[:10])
        #打印当前模型在测试集得到的分数
        print("%s Score: %0.2f" % (k, estimators[k].score(X_test, y_test)))
        scores = cross_val_score(estimators[k], X_train, y_train,scoring='accuracy' ,cv=10)
        print("%s Cross Avg. Score: %0.2f (+/- %0.2f)" % (k, scores.mean(), scores.std() * 2))
        end_time = datetime.datetime.now()
        time_spend = end_time - start_time
        print("%s Time: %0.2f" % (k, time_spend.total_seconds()))
        
        #对所有训练集都给出模型预测
        dating_dec = estimators[k].predict(ds)
        #print(dating_dec)
        
        print("id\tdim1\t\tdim2\t\tdim3\t\t标签  面向用例的程度\t模型预测")
        
        # 制表函数
        # 为方便观察，只选取30个制表（模型训练结果与实际情况的对比表）
        for i in range(80, 110):
            print(i-79, end='\t')
            print('%.3f' %ds[i][0], end='\t\t')
            print('%.3f' %ds[i][1], end='\t\t')
            print('%.1f' %ds[i][2], end='\t\t')
            print(int(ts[i]), end='\t')
            if ts[i]<=20:
                print('低', end='\t\t')
            elif ts[i]<80:
                print('中', end='\t\t')
            else:
                print("高", end='\t\t')
            
            if dating_dec[i]<=20:
                print('低')
            elif dating_dec[i]<80:
                print('中')
            else:
                print("高")
        
        #取所有的模型训练结果绘图
        little=[]
        middle=[]
        higher=[]
        
        for i in range(len(dating_dec)):
            if dating_dec[i]<=20:
                little.append(ds[i])
            elif dating_dec[i]<80:
                middle.append(ds[i])
            else:
                higher.append(ds[i])
        
        l=np.array(little)
        m=np.array(middle)
        h=np.array(higher)
        #print(little)
        
        x1=l[:, 0]
        y1=l[:, 1]
        z1=l[:, 2]
        
        x2=m[:, 0]
        y2=m[:, 1]
        z2=m[:, 2]
        
        x3=h[:, 0]
        y3=h[:, 1]
        z3=h[:, 2]
        
        fig = plt.figure()
        ax = Axes3D(fig)
        ax.scatter(x1, y1, z1, c='g', label='little')
        ax.scatter(x2, y2, z2, c='y', label='middle')
        ax.scatter(x3, y3, z3, c='r', label='higher')
        
        ax.legend(loc='best')
        ax.set_zlabel('Z', fontdict={'size': 10, 'color': 'black'})
        ax.set_ylabel('Y', fontdict={'size': 10, 'color': 'black'})
        ax.set_xlabel('X', fontdict={'size': 10, 'color': 'black'})
        ax.set_title('%s Model prediction results' % k)
        
        plt.show()
            
        

#所有人的数据集汇总后开始测试
def coach_text_RF_all():
    
    #deleten() 规范化数据集，去除文件中的\n
    
    #训练集路径
    path="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/dataSet_deleten2.txt"
    
    ds=[]#数据集
    ts=[]#标签数据范围0~1之间的浮点数（保留两位小数）
    
    for line in open(path, encoding='utf-8'):
        if line[:2]=="[[":
            ds=eval(line)
        else:
            ts=eval(line)
    
    ds=ds[70:]
    ts=ts[70:]
            
    
    #控制ts数据类型为0~100内的整数
    for i in range(len(ts)):
        ts[i]*=100
    
    #决策树与随机森林的模型训练
    #还包含数据可视化：模型训练结果与实际情况的对比表；  所有的模型训练预测结果图谱
    TreeforestTest(ds, ts)

#数据集的图像化展示
def showpriture():
    
    pathgetTG="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/dataSet_deleten2.txt"
    
    ds=[]
    ts=[]
    
    for line in open(pathgetTG, encoding='utf-8'):
        if line[:2]=="[[":
            ds=eval(line)
        else:
            ts=eval(line)
    
    for i in range(len(ts)):
        ts[i]*=100
    
    #数据清洗
    ds=ds[70:]
    ts=ts[70:]
    
    tmp=0
    while tmp<len(ds):
        if(ds[tmp][0]>=1):
            ds.pop(tmp)
            ts.pop(tmp)
            tmp-=1
        tmp+=1
        
    little=[]
    middle=[]
    higher=[]
    
    #print(len(ds))
    
    pathl="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/little.xls"
    pathm="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/middle.xls"
    pathh="D:/Undergraduate/School Work/#Sophomore/down/数据科学基础/大作业/high.xls"
    #d=np.array(ds)
        
    for i in range(len(ds)):
        if ts[i]<=20:
            little.append(ds[i])
        elif ts[i]<80:
            middle.append(ds[i])
        else:
            higher.append(ds[i])
    
    l=np.array(little)
    m=np.array(middle)
    h=np.array(higher)
    #print(little)
    
    save(l, pathl)
    save(m, pathm)
    save(h, pathh)
    
    x1=l[:, 0]
    y1=l[:, 1]
    z1=l[:, 2]
    
    x2=m[:, 0]
    y2=m[:, 1]
    z2=m[:, 2]
    
    x3=h[:, 0]
    y3=h[:, 1]
    z3=h[:, 2]
    
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.scatter(x1, y1, z1, c='g', label='little')
    ax.scatter(x2, y2, z2, c='c', label='middle')
    ax.scatter(x3, y3, z3, c='r', label='higher')
    
    ax.legend(loc='best')
    ax.set_zlabel('Z', fontdict={'size': 10, 'color': 'black'})
    ax.set_ylabel('Y', fontdict={'size': 10, 'color': 'black'})
    ax.set_xlabel('X', fontdict={'size': 10, 'color': 'black'})
    ax.set_title('Data set actual results')
    
    plt.show()

        
#保存训练集为xls文件
def save(data, path):
    f = xlwt.Workbook()  # 创建工作簿
    sheet1 = f.add_sheet(u'sheet1', cell_overwrite_ok=True)  # 创建sheet
    [h, l] = data.shape  # h为行数，l为列数
    for i in range(h):
        for j in range(l):
            sheet1.write(i, j, data[i, j])
    f.save(path)
    

if __name__ == '__main__':
    
    coach_text_RF_all()
    
    showpriture()
    